package br.org.mestrado.vais;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;

public enum PROBLEMA {

	DTLZ1 {
		@Override
		public void eval(Anticorpo anticorpo, boolean isStart) {

			int i = 0;
			int j = 0;
			int n = anticorpo.getDecisionVariables().length;
			int k = n - anticorpo.getObjectives().length + 1;

			double g = 0;
			for (i = n - k + 1; i <= n; i++) {
				g += Math.pow(anticorpo.getDecisionVariables()[i - 1] - 0.5, 2)
						- Math
								.cos(20
										* Math.PI
										* (anticorpo.getDecisionVariables()[i - 1] - 0.5));
			}
			g = 100 * (k + g);

			for (i = 1; i <= anticorpo.getObjectives().length; i++) {
				double f = 0.5 * (1 + g);
				for (j = anticorpo.getObjectives().length - i; j >= 1; j--) {
					f *= anticorpo.getDecisionVariables()[j - 1];
				}
				if (i > 1) {
					f *= 1 - anticorpo.getDecisionVariables()[(anticorpo
							.getObjectives().length
							- i + 1) - 1];
				}

				anticorpo.getObjectives()[i - 1] = f;
			}
		}

		@Override
		public boolean insideDomain(int pointer, double... objectives) {

			// teclado não tem pipe
			if (objectives[pointer] < 0d) {
				return false;
			}
			if (objectives[pointer] > 1d) {
				return false;
			}

			return true;
		}

		@Override
		public int[] chooseVariables(final double[] ranges,
				final int totalVariablesToMutate) {

			final int[] vars = new int[totalVariablesToMutate];

			for (int pointer = vars.length - 1; pointer > -1; pointer--) {

				// adiciona no array
				vars[pointer] = pointer;

			}

			return vars;

		}

		@Override
		public boolean isConstrained(Anticorpo anticorpo) {
			return true;
		}

		@Override
		public void startDecisionVar(double[] vars, int pointer) {

			vars[pointer] = Math.random();

		}
	},
	DTLZ2 {
		@Override
		public void eval(Anticorpo anticorpo, boolean isStart) {

			double g = 0d;

			for (int i = 0; i < anticorpo.getDecisionVariables().length; i++) {
				g += Math.pow((anticorpo.getDecisionVariables()[i] - 0.5), 2);
			}

			double pi_2 = Math.PI / 2.0;

			double f0 = (1 + g)
					* Math.cos(anticorpo.getDecisionVariables()[0] * pi_2);

			for (int i = 1; i < anticorpo.getObjectives().length - 1; i++) {
				f0 *= Math.cos(anticorpo.getDecisionVariables()[i] * pi_2);

			}

			final BigDecimal bigDecimal = new BigDecimal(f0, VAIS.MATH_CONTEXT);

			anticorpo.getObjectives()[0] = bigDecimal.doubleValue();

			for (int i = 1; i < (anticorpo.getObjectives().length); i++) {
				double fxi = (1 + g);
				int j = 1;
				for (j = 0; j < (anticorpo.getObjectives().length - 1 - i); j++) {
					fxi *= (Math
							.cos(anticorpo.getDecisionVariables()[j] * pi_2));

				}
				fxi *= (Math.sin(anticorpo.getDecisionVariables()[j] * pi_2));

				final BigDecimal bigDecimalfx = new BigDecimal(fxi,
						VAIS.MATH_CONTEXT);

				anticorpo.getObjectives()[i] = bigDecimalfx.doubleValue();
			}

			if (!isStart)
				fitnessCout.incrementAndGet();

		}

		@Override
		public boolean insideDomain(int pointer, double... objectives) {
			// teclado não tem pipe
			if (objectives[pointer] < 0d || objectives[pointer] > 1d) {
				return false;
			}

			return true;
		}

		@Override
		public boolean isConstrained(Anticorpo anticorpo) {

			return true;
		}

		@Override
		public void startDecisionVar(double[] vars, int pointer) {

			final BigDecimal bigDecimal = new BigDecimal(Math.random(),
					VAIS.MATH_CONTEXT);

			vars[pointer] = bigDecimal.doubleValue();

		}
	},
	DTLZ3 {
		@Override
		public void eval(Anticorpo anticorpo, boolean isStart) {
			int i = 0;
			int j = 0;
			int n = anticorpo.getDecisionVariables().length;
			int k = n - anticorpo.getObjectives().length + 1;

			double g = 0;
			for (i = n - k + 1; i <= n; i++) {
				g += Math.pow(anticorpo.getDecisionVariables()[i - 1] - 0.5, 2)
						- Math
								.cos(20
										* Math.PI
										* (anticorpo.getDecisionVariables()[i - 1] - 0.5));
			}
			g = 100 * (k + g);

			for (i = 1; i <= anticorpo.getObjectives().length; i++) {
				double f = (1 + g);
				for (j = anticorpo.getObjectives().length - i; j >= 1; j--) {
					f *= Math.cos(anticorpo.getDecisionVariables()[j - 1]
							* Math.PI / 2);
				}
				if (i > 1) {
					f *= Math.sin(anticorpo.getDecisionVariables()[(anticorpo
							.getObjectives().length
							- i + 1) - 1]
							* Math.PI / 2);
				}

				anticorpo.getObjectives()[i - 1] = f;
			}
		}

		@Override
		public boolean insideDomain(int pointer, double... objectives) {
			return false;
		}

		@Override
		public int[] chooseVariables(double[] ranges, int totalVariablesToMutate) {
			return null;
		}

		@Override
		public boolean isConstrained(Anticorpo anticorpo) {
			return true;
		}

		@Override
		public void startDecisionVar(double[] vars, int pointer) {

		}
	},
	DTLZ4 {

		@Override
		public void eval(Anticorpo anticorpo, boolean isStart) {

			double g = 0d;

			for (int i = 0; i < anticorpo.getDecisionVariables().length; i++) {
				g += Math.pow((anticorpo.getDecisionVariables()[i] - 0.5), 2);
			}

			double pi_2 = Math.PI / 2.0;

			final double alpha = 100;

			double xiAlpha = Math.pow(anticorpo.getObjectives()[0], alpha);

			double f0 = (1 + g) * Math.cos(xiAlpha * pi_2);

			for (int i = 1; i < anticorpo.getObjectives().length - 1; i++) {

				f0 *= Math.cos(anticorpo.getDecisionVariables()[i] * pi_2);
			}

			anticorpo.getObjectives()[0] = new BigDecimal(f0, VAIS.MATH_CONTEXT)
					.doubleValue();

			for (int i = 1; i < (anticorpo.getObjectives().length); i++) {

				double fxi = (1 + g);

				int j = 1;

				for (j = 0; j < (anticorpo.getObjectives().length - 1 - i); j++) {

					xiAlpha = Math.pow(anticorpo.getDecisionVariables()[j],
							alpha);

					fxi *= (Math.cos(xiAlpha * pi_2));
				}

				xiAlpha = Math.pow(anticorpo.getDecisionVariables()[j], alpha);

				fxi *= (Math.sin(xiAlpha * pi_2));

				anticorpo.getObjectives()[i] = new BigDecimal(fxi,
						VAIS.MATH_CONTEXT).doubleValue();
			}

			if (!isStart)
				fitnessCout.incrementAndGet();

		}

		@Override
		public boolean insideDomain(int pointer, double... objectives) {
			// teclado não tem pipe
			if (objectives[pointer] < 0d || objectives[pointer] > 1d) {
				return false;
			}

			return true;
		}

		@Override
		public boolean isConstrained(Anticorpo anticorpo) {
			return true;
		}

		@Override
		public void startDecisionVar(double[] vars, int pointer) {

			final BigDecimal bigDecimal = new BigDecimal(Math.random(),
					VAIS.MATH_CONTEXT);

			vars[pointer] = bigDecimal.doubleValue();
		}
	},
	DTLZ5 {
		@Override
		public void eval(Anticorpo anticorpo, boolean isStart) {
			int i = 0;
			int j = 0;
			int n = anticorpo.getDecisionVariables().length;
			int k = n - anticorpo.getObjectives().length + 1;

			double[] theta = new double[anticorpo.getObjectives().length];
			double t = 0;
			double g = 0;

			for (i = n - k + 1; i <= n; i++) {
				g += Math.pow(anticorpo.getDecisionVariables()[i - 1] - 0.5, 2);
			}

			t = Math.PI / (4 * (1 + g));
			theta[0] = anticorpo.getDecisionVariables()[0] * Math.PI / 2;
			for (i = 2; i <= anticorpo.getObjectives().length - 1; i++) {
				theta[i - 1] = t
						* (1 + 2 * g * anticorpo.getDecisionVariables()[i - 1]);
			}

			for (i = 1; i <= anticorpo.getObjectives().length; i++) {
				double f = (1 + g);
				for (j = anticorpo.getObjectives().length - i; j >= 1; j--) {
					f *= Math.cos(theta[j - 1]);
				}
				if (i > 1) {
					f *= Math
							.sin(theta[(anticorpo.getObjectives().length - i + 1) - 1]);
				}

				anticorpo.getObjectives()[i - 1] = f;
			}
		}

		@Override
		public boolean insideDomain(int pointer, double... objectives) {
			return false;
		}

		@Override
		public int[] chooseVariables(double[] ranges, int totalVariablesToMutate) {
			return null;
		}

		@Override
		public boolean isConstrained(Anticorpo anticorpo) {
			return true;
		}

		@Override
		public void startDecisionVar(double[] vars, int pointer) {

		}
	},
	DTLZ6 {
		@Override
		public void eval(Anticorpo anticorpo, boolean isStart) {
			int i = 0;
			int j = 0;
			int n = anticorpo.getDecisionVariables().length;
			int k = n - anticorpo.getObjectives().length + 1;

			double[] theta = new double[anticorpo.getObjectives().length];
			double t = 0;
			double g = 0;

			for (i = n - k + 1; i <= n; i++) {
				g += Math.pow(anticorpo.getDecisionVariables()[i - 1], 0.1);
			}

			t = Math.PI / (4 * (1 + g));
			theta[0] = anticorpo.getDecisionVariables()[0] * Math.PI / 2;
			for (i = 2; i <= anticorpo.getObjectives().length - 1; i++) {
				theta[i - 1] = t
						* (1 + 2 * g * anticorpo.getDecisionVariables()[i - 1]);
			}

			for (i = 1; i <= anticorpo.getObjectives().length; i++) {
				double f = (1 + g);
				for (j = anticorpo.getObjectives().length - i; j >= 1; j--) {
					f *= Math.cos(theta[j - 1]);
				}
				if (i > 1) {
					f *= Math
							.sin(theta[(anticorpo.getObjectives().length - i + 1) - 1]);
				}

				anticorpo.getObjectives()[i - 1] = f;
			}
		}

		@Override
		public boolean insideDomain(int pointer, double... objectives) {
			return false;
		}

		@Override
		public int[] chooseVariables(double[] ranges, int totalVariablesToMutate) {
			return null;
		}

		@Override
		public boolean isConstrained(Anticorpo anticorpo) {
			return true;
		}

		@Override
		public void startDecisionVar(double[] vars, int pointer) {

		}
	},
	DTLZ7 {
		@Override
		public void eval(Anticorpo anticorpo, boolean isStart) {
			int i = 0;
			int j = 0;
			int n = anticorpo.getDecisionVariables().length;
			int k = n - anticorpo.getObjectives().length + 1;

			double g = 0;
			double h = 0;

			for (i = n - k + 1; i <= n; i++) {
				g += anticorpo.getDecisionVariables()[i - 1];
			}
			g = 1 + 9 * g / k;

			for (i = 1; i <= anticorpo.getObjectives().length - 1; i++) {
				anticorpo.getObjectives()[i - 1] = anticorpo
						.getDecisionVariables()[i - 1];
			}

			for (j = 1; j <= anticorpo.getObjectives().length - 1; j++) {
				h += anticorpo.getDecisionVariables()[j - 1]
						/ (1 + g)
						* (1 + Math.sin(3 * Math.PI
								* anticorpo.getDecisionVariables()[j - 1]));
			}

			h = anticorpo.getObjectives().length - h;

			anticorpo.getObjectives()[anticorpo.getObjectives().length - 1] = (1 + g)
					* h;
		}

		@Override
		public boolean insideDomain(int pointer, double... objectives) {
			return false;
		}

		@Override
		public int[] chooseVariables(double[] ranges, int totalVariablesToMutate) {
			return null;
		}

		@Override
		public boolean isConstrained(Anticorpo anticorpo) {
			return true;
		}

		@Override
		public void startDecisionVar(double[] vars, int pointer) {

		}
	},
	DTLZ8 {
		@Override
		public void eval(Anticorpo anticorpo, boolean isStart) {

		}

		@Override
		public boolean insideDomain(int pointer, double... objectives) {
			return false;
		}

		@Override
		public int[] chooseVariables(double[] ranges, int totalVariablesToMutate) {
			return null;
		}

		@Override
		public boolean isConstrained(Anticorpo anticorpo) {
			return true;
		}

		@Override
		public void startDecisionVar(double[] vars, int pointer) {

		}
	},
	DTLZ9 {
		@Override
		public void eval(Anticorpo anticorpo, boolean isStart) {

		}

		@Override
		public boolean insideDomain(int pointer, double... objectives) {
			return false;
		}

		@Override
		public int[] chooseVariables(double[] ranges, int totalVariablesToMutate) {
			return null;
		}

		@Override
		public boolean isConstrained(Anticorpo anticorpo) {
			return true;
		}

		@Override
		public void startDecisionVar(double[] vars, int pointer) {

		}
	},
	TANAKA {

		@Override
		public void eval(final Anticorpo anticorpo, boolean isStart) {

			// testa se possui duas variaveis objetivos
			assert anticorpo.getObjectives().length == 2;

			// testa se possui duas variaveis de decisão
			assert anticorpo.getDecisionVariables().length == 2;

			anticorpo.getObjectives()[0] = anticorpo.getDecisionVariables()[0];

			anticorpo.getObjectives()[1] = anticorpo.getDecisionVariables()[1];

		}

		@Override
		public boolean insideDomain(int pointer, double... objectives) {
			// teclado não tem pipe
			if (objectives[pointer] < 0.0d) {
				return false;
			}
			if (objectives[pointer] > Math.PI) {
				return false;
			}

			return true;
		}

		@Override
		public boolean isConstrained(Anticorpo anticorpo) {

			double var_l1 = anticorpo.getDecisionVariables()[0];

			double var_l2 = anticorpo.getDecisionVariables()[1];

			// verifica retrição 1
			double c_1_l = new BigDecimal(Math.cos(16 * Math.atan(var_l1
					/ var_l2)), VAIS.MATH_CONTEXT).doubleValue();

			double c_1_ll = new BigDecimal(Math.pow(var_l1, 2)
					+ Math.pow(var_l2, 2), VAIS.MATH_CONTEXT).doubleValue();

			double c_1 = new BigDecimal(c_1_ll - 1 - (0.1 * c_1_l),
					VAIS.MATH_CONTEXT).doubleValue();

			// verifica restrição 2
			double c_2 = new BigDecimal(Math.pow(var_l1 - 0.5, 2)
					+ Math.pow(var_l2 - 0.5, 2), VAIS.MATH_CONTEXT)
					.doubleValue();

			if (c_1 < 0.0d || c_2 > 0.5d)
				return false;

			return true;
		}

		@Override
		public void startDecisionVar(double[] vars, int pointer) {

			vars[pointer] = new BigDecimal(Math.random() * Math.PI,
					VAIS.MATH_CONTEXT).doubleValue();

		}
	},
	DEB1999 {

		@Override
		public void eval(Anticorpo anticorpo, boolean isStart) {

			// testa se possui duas variaveis objetivos
			assert anticorpo.getObjectives().length == 2;

			// testa se possui duas variaveis de decisão
			assert anticorpo.getDecisionVariables().length == 2;

			double f = anticorpo.getDecisionVariables()[0];

			anticorpo.getObjectives()[0] = new BigDecimal(f, VAIS.MATH_CONTEXT)
					.doubleValue();

			double g1 = new BigDecimal(anticorpo.getDecisionVariables()[1],
					VAIS.MATH_CONTEXT).doubleValue();

			double gl1 = new BigDecimal(Math.exp(-Math.pow((g1 - 0.2) / 0.004,
					2)), VAIS.MATH_CONTEXT).doubleValue();

			double gl2 = new BigDecimal(Math
					.exp(-Math.pow((g1 - 0.6) / 0.4, 2)), VAIS.MATH_CONTEXT)
					.doubleValue();

			double g = new BigDecimal(2 - gl1 - (0.8 * gl2), VAIS.MATH_CONTEXT)
					.doubleValue();

			f = g / anticorpo.getDecisionVariables()[0];

			anticorpo.getObjectives()[1] = new BigDecimal(f, VAIS.MATH_CONTEXT)
					.doubleValue();

			fitnessCout.incrementAndGet();

		}

		@Override
		public boolean insideDomain(int pointer, double... objectives) {
			// teclado não tem pipe
			if (objectives[pointer] < 0.1d || objectives[pointer] > 1d) {
				return false;
			}

			return true;
		}

		@Override
		public boolean isConstrained(Anticorpo anticorpo) {
			return true;
		}

		@Override
		public void startDecisionVar(double[] vars, int pointer) {

			vars[pointer] = new BigDecimal(Math.random(), VAIS.MATH_CONTEXT)
					.doubleValue();

		}
	},
	ZITZILER {

		@Override
		public void eval(Anticorpo anticorpo, boolean isStart) {

			// testa se possui duas variaveis objetivos
			assert anticorpo.getObjectives().length == 2;

			double var_l = anticorpo.getDecisionVariables()[0];

			double gl1 = new BigDecimal(Math.exp((-4 * var_l)),
					VAIS.MATH_CONTEXT).doubleValue();

			double gl2 = new BigDecimal(Math.pow(Math.sin(6 * Math.PI * var_l),
					6), VAIS.MATH_CONTEXT).doubleValue();

			// calcula próximo objetivo
			double f1 = 1 - (gl1 * gl2);

			anticorpo.getObjectives()[0] = new BigDecimal(f1, VAIS.MATH_CONTEXT)
					.doubleValue();

			// cálcula próximo objetivo
			double g = 0;

			double w_t = 0;

			for (int pointer = 1; pointer < anticorpo.getDecisionVariables().length; pointer++) {
				w_t = new BigDecimal(w_t
						+ anticorpo.getDecisionVariables()[pointer],
						VAIS.MATH_CONTEXT).doubleValue();
			}

			gl1 = new BigDecimal(w_t
					/ (anticorpo.getDecisionVariables().length - 1),
					VAIS.MATH_CONTEXT).doubleValue();

			g = new BigDecimal(1 + (9 * Math.pow(gl1, 0.25)), VAIS.MATH_CONTEXT)
					.doubleValue();

			gl2 = new BigDecimal(Math.pow(f1 / g, 2), VAIS.MATH_CONTEXT)
					.doubleValue();

			double f2 = 0;

			f2 = 1 - gl2;

			anticorpo.getObjectives()[1] = new BigDecimal(f2, VAIS.MATH_CONTEXT)
					.doubleValue();

			fitnessCout.incrementAndGet();

		}

		@Override
		public boolean insideDomain(final int pointer, double... objectives) {

			// teclado não tem pipe
			if (objectives[pointer] < 0d || objectives[pointer] > 1d) {
				return false;
			}

			return true;
		}

		@Override
		public boolean isConstrained(Anticorpo anticorpo) {
			return true;
		}

		@Override
		public void startDecisionVar(double[] vars, int pointer) {

			vars[pointer] = new BigDecimal(Math.random(), VAIS.MATH_CONTEXT)
					.doubleValue();

		}
	},
	OSYCZKA1995 {

		@Override
		public void eval(Anticorpo anticorpo, boolean isStart) {
			// testa se possui duas variaveis objetivos
			assert anticorpo.getObjectives().length == 2;

			// testa se possui seis variaveis objetivos
			assert anticorpo.getDecisionVariables().length == 6;

			// formatação de valores intermediários
			double gl1 = new BigDecimal(Math.pow(anticorpo
					.getDecisionVariables()[0] - 2, 2), VAIS.MATH_CONTEXT)
					.doubleValue();

			double gl2 = new BigDecimal(Math.pow(anticorpo
					.getDecisionVariables()[1] - 2, 2), VAIS.MATH_CONTEXT)
					.doubleValue();

			double gl3 = new BigDecimal(Math.pow(anticorpo
					.getDecisionVariables()[2] - 2, 2), VAIS.MATH_CONTEXT)
					.doubleValue();

			double gl4 = new BigDecimal(Math.pow(anticorpo
					.getDecisionVariables()[3] - 2, 2), VAIS.MATH_CONTEXT)
					.doubleValue();

			double gl5 = new BigDecimal(Math.pow(anticorpo
					.getDecisionVariables()[4] - 2, 2), VAIS.MATH_CONTEXT)
					.doubleValue();

			// f1
			double f1 = -((25 * gl1) + gl2 + gl3 + gl4 + gl5);

			// f2
			double f2 = 0d;

			for (double var : anticorpo.getDecisionVariables()) {
				f2 += new BigDecimal(Math.pow(var, 2), VAIS.MATH_CONTEXT)
						.doubleValue();
			}

			anticorpo.getObjectives()[0] = new BigDecimal(f1, VAIS.MATH_CONTEXT)
					.doubleValue();

			anticorpo.getObjectives()[1] = new BigDecimal(f2, VAIS.MATH_CONTEXT)
					.doubleValue();

		}

		@Override
		public boolean insideDomain(int pointer, double... objectives) {

			if ((pointer == 0 || pointer == 1 || pointer == 5)
					&& (objectives[pointer] < 0 || objectives[pointer] > 10))
				return false;
			if ((pointer == 2 || pointer == 4)
					&& (objectives[pointer] < 1 || objectives[pointer] > 5))
				return false;
			if (objectives[pointer] < 0 || objectives[pointer] > 6)
				return false;

			return true;
		}

		@Override
		public boolean isConstrained(Anticorpo anticorpo) {

			// valida restrição 1
			double c1 = new BigDecimal(anticorpo.getDecisionVariables()[0]
					+ anticorpo.getDecisionVariables()[1] - 2,
					VAIS.MATH_CONTEXT).doubleValue();

			// valida restrição 2
			double c2 = new BigDecimal(6 - anticorpo.getDecisionVariables()[0]
					- anticorpo.getDecisionVariables()[1], VAIS.MATH_CONTEXT)
					.doubleValue();

			// valida restrição 3
			double c3 = new BigDecimal(2 + anticorpo.getDecisionVariables()[0]
					- anticorpo.getDecisionVariables()[1], VAIS.MATH_CONTEXT)
					.doubleValue();

			// valida restrição 4
			double c4 = new BigDecimal(2 - anticorpo.getDecisionVariables()[0]
					+ (3 * anticorpo.getDecisionVariables()[1]),
					VAIS.MATH_CONTEXT).doubleValue();

			// valide restrição 5
			double c5 = new BigDecimal(4
					- Math.pow(anticorpo.getDecisionVariables()[2] - 3, 2)
					- anticorpo.getDecisionVariables()[3], VAIS.MATH_CONTEXT)
					.doubleValue();

			// valida restrição 6
			double c6 = new BigDecimal(Math.pow(anticorpo
					.getDecisionVariables()[4] - 3, 2)
					+ anticorpo.getDecisionVariables()[5] - 4,
					VAIS.MATH_CONTEXT).doubleValue();

			if (c1 < 0 || c2 < 0 || c3 < 0 || c4 < 0 || c5 < 0 || c6 < 0)
				return false;

			return true;
		}

		@Override
		public void startDecisionVar(double[] vars, int pointer) {

			// não tem pipe
			if (pointer == 0 || pointer == 1 || pointer == 5)
				vars[pointer] = new BigDecimal(Math.random() * 10,
						VAIS.MATH_CONTEXT).doubleValue();
			if (pointer == 2 || pointer == 4)
				vars[pointer] = new BigDecimal(Math.random() * 5,
						VAIS.MATH_CONTEXT).doubleValue();
			if (pointer == 3)
				vars[pointer] = new BigDecimal(Math.random() * 6,
						VAIS.MATH_CONTEXT).doubleValue();
		}

	},

	KITA1996 {

		@Override
		public void eval(final Anticorpo anticorpo, boolean isStart) {
			// testa se possui duas variaveis objetivos
			assert anticorpo.getObjectives().length == 2;

			// testa se possui seis variaveis objetivos
			assert anticorpo.getDecisionVariables().length == 2;

			double var1 = anticorpo.getDecisionVariables()[0];

			double var2 = anticorpo.getDecisionVariables()[1];

			double f1 = (Math.pow(var1, 2) * -1) + var2;

			double f2 = (0.5 * var1) + var2 + 1;

			anticorpo.getObjectives()[0] = f1;

			anticorpo.getObjectives()[1] = f2;

		}

		@Override
		public boolean insideDomain(int pointer, double... objectives) {

			if (objectives[pointer] < 0 || objectives[pointer] > 7)
				return false;

			return true;
		}

		@Override
		public boolean isConstrained(Anticorpo anticorpo) {

			double var1 = anticorpo.getDecisionVariables()[0];

			double var2 = anticorpo.getDecisionVariables()[1];

			double c1 = ((1 / 6) * var1) + var2 - (13 / 2);

			double c2 = ((1 / 2) * var1) + var2 - (15 / 2);

			double c3 = (5 * var1) + var2 - 30;

			if (c1 > 0 || c2 > 0 || c3 > 0)
				return false;

			return true;
		}

		@Override
		public void startDecisionVar(double[] vars, int pointer) {

			vars[pointer] = Math.random() * 7d;

		}

	};

	public abstract void eval(final Anticorpo anticorpo, boolean isStart);

	public abstract boolean insideDomain(int pointer,
			final double... objectives);

	public int[] chooseVariables(final double[] ranges,
			final int totalVariablesToMutate) {

		final int[] vars = new int[totalVariablesToMutate];

		if (totalVariablesToMutate > 0) {

			Arrays.fill(vars, -1);

			final boolean[] tmp = new boolean[ranges.length];

			Arrays.fill(tmp, true);

			int pointer = 0;

			final Random random = new Random(System.currentTimeMillis() / 1000);

			do {

				final double r = random.nextDouble();

				for (int j = 0; j < ranges.length; j++) {

					if (tmp[j]) {
						if (j == 0 && r <= ranges[j]) {
							vars[pointer] = j;
						} else if (j > 0 && r > ranges[j - 1] && r <= ranges[j]) {
							vars[pointer] = j;

						}
						if (vars[pointer] != -1) {
							pointer += 1;

							tmp[j] = false;

							break;
						}
					}
				}
			} while (pointer < vars.length);
		}
		return vars;

	}

	public abstract boolean isConstrained(final Anticorpo anticorpo);

	public abstract void startDecisionVar(final double[] vars, int pointer);

	AtomicInteger fitnessCout = new AtomicInteger();

	int maxFitnessTotal = 0;

	public boolean stopNow() {

		return fitnessCout.get() >= maxFitnessTotal;

	}

	public void setMaxFitnessCount(final int max) {
		maxFitnessTotal = max;

	}

}
